﻿#ifndef HGL_STACK_CPP
#define HGL_STACK_CPP

#include<hgl/LogInfo.h>
namespace hgl
{
	/**
	* 本类构造函数
	* @param m 如果m的值不为0，则表示使用固定的堆栈大小。固定大小的堆栈会在一开始即分配好内存。
	*/
	template<typename T>
	Stack<T>::Stack(int m)
	{
		count=0;

		if(m)
		{
			max_count=m;

			items=(T *)hgl_malloc(max_count*sizeof(T));
		}
		else
			max_count=0;

		mem_count=max_count;
	}

	template<typename T>
	Stack<T>::~Stack()
	{
		if(count||max_count)hgl_free(items);
	}

	/**
	* 修改堆栈的最大值
	*/
	template<typename T>
	void Stack<T>::SetMax(int m)
	{
		if(max_count||(!max_count&&count))
			items=(T *)hgl_realloc(items,m*sizeof(T));
		else
			items=(T *)hgl_malloc(m*sizeof(T));

		max_count=m;
		mem_count=m;

		if(count>=max_count)count=max_count-1;
	}

	/**
	* 清除堆栈中的所有数据
	*/
	template<typename T>
	void Stack<T>::Clear()
	{
		if(max_count==0)
			if(count)
			{
				hgl_free(items);
				mem_count=0;
			}

		count=0;
	}

	template<typename T>
	T &Stack<T>::GetItem(int n)
	{
		if(n<0||n>=count)
		{
			LOG_ERROR(OS_TEXT("从堆栈中按索引<") + OSString(n) + OS_TEXT(">取数据，超出正常范围<")+OSString(count) + OS_TEXT(">"));

			return(*(T *)NULL);
		}

		return(items[n]);
	}

	/**
	* 访问堆栈中的一个数据，但不清除它
	* @param t 取出的数据保存地
	* @return 是否成功取出数据
	*/
	template<typename T>
	bool Stack<T>::Peek(T &t)
	{
		if(count)
		{
			memcpy(&t,items+(count-1),sizeof(T));
//			t=items[count-1];
			return(true);
		}
		else
			return(false);
	}

	/**
	* 从堆栈中取出一个数据
	* @param t 取出的数据保存地
	* @return 是否成功取出数据
	*/
	template<typename T>
	bool Stack<T>::Pop(T &t)
	{
		if(count)
		{
//			t=items[--count];
			count--;
			memcpy(&t,items+count,sizeof(T));

			if(max_count==0)
			{
				if(count==0)
				{
					hgl_free(items);

					mem_count=0;
				}
				//else
					//items=(T *)hgl_realloc(items,count*sizeof(T));
			}

			return(true);
		}
		else
			return(false);
	}

	/**
	* 向堆栈中放入一个数据
	* @param data 要放入的数据指针
	* @return true 放入数据成功
	* @return false 放入数据失败
	*/
	template<typename T>
	bool Stack<T>::Push(T &data)
	{
		if(max_count)
		{
			if(count>=max_count)return(false);
		}
		else
		{
			if(count)
			{
				if(count+1>mem_count)
				{
					mem_count=count+1;

					items=(T *)hgl_realloc(items,mem_count*sizeof(T));
				}
			}
			else
			{
				items=(T *)hgl_malloc(sizeof(T));

				mem_count=1;
			}
		}

//		items[count++]=data;
		memcpy(items+count,&data,sizeof(T));
		count++;

		return(true);
	}

	/**
	* 向堆栈中放入多个数据
	* @param data 要放入的数据
	* @param data_count 要放入的数据个数
	* @return true 放入数据成功
	* @return false 放入数据失败
	*/
	template<typename T>
	bool Stack<T>::Push(T *data,int data_count)
	{
		if(max_count)
		{
			if(count>=max_count)return(false);
		}
		else
		{
			if(count)
			{
				if(count+data_count>mem_count)
				{
					mem_count=count+data_count;

					items=(T *)hgl_realloc(items,mem_count*sizeof(T));
				}
			}
			else
			{
				items=(T *)hgl_malloc(data_count*sizeof(T));

				mem_count=data_count;
			}
		}

		memcpy(items+count,data,data_count*sizeof(T));
		count+=data_count;

		return(true);
	}

	template<typename T>
	void Stack<T>::operator =(const Stack<T> &ori)
	{
		if(ori.count==0)return;

		Clear();

		max_count=ori.count;
		count=ori.count;

		if(max_count==0)
			mem_count=count;
		else
			mem_count=max_count;

		items=(T *)hgl_malloc(mem_count*sizeof(T));

		memcpy(items,ori.items,mem_count*sizeof(T));
	}
}//namespace hgl

namespace hgl
{
	template<typename T>
	void StackObject<T>::Clear()
	{
		for(int i=0;i<this->count;i++)
			delete this->items[i];

		Stack<T *>::Clear();
	}
}//namespace hgl
#endif//HGL_STACK_CPP
